package com.example.exodemo;

import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.ViewTreeObserver;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.ui.PlayerView;

import com.example.exodemo.lrc.DefaultLrcParser;
import com.example.exodemo.lrc.LrcRow;
import com.example.exodemo.lrc.LrcView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

public class PlayerActivity extends AppCompatActivity {

    private static final String TAG = "PlayerActivity";
    private ExoPlayer player;
    private PlayerView playerView;
    private LrcView mLrcView;

    private final Handler lyricsUpdateHandler = new Handler(Looper.getMainLooper());
    private boolean lrcIsLoaded = false; // Flag to indicate if LRC data is parsed and set

    // Saved instance state keys
    private static final String KEY_PLAYBACK_POSITION = "playbackPosition";
    private static final String KEY_CURRENT_WINDOW = "currentWindow";
    private static final String KEY_PLAY_WHEN_READY = "playWhenReady";

    private long playbackPosition = 0;
    private int currentWindow = 0;
    private boolean playWhenReady = true;


    private final Runnable lyricsUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            if (player != null && player.isPlaying() && lrcIsLoaded && mLrcView != null) {
                long currentPosition = player.getCurrentPosition();
                mLrcView.seekTo(currentPosition, false, false);
                // Schedule the next update only if still playing
                lyricsUpdateHandler.postDelayed(this, 250); // Adjust delay as needed (e.g., 100-300ms)
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_player);

        playerView = findViewById(R.id.player_view);
        mLrcView = findViewById(R.id.lrcview);

        if (savedInstanceState != null) {
            playbackPosition = savedInstanceState.getLong(KEY_PLAYBACK_POSITION);
            currentWindow = savedInstanceState.getInt(KEY_CURRENT_WINDOW);
            playWhenReady = savedInstanceState.getBoolean(KEY_PLAY_WHEN_READY);
        }

        Intent intent = getIntent();
        Uri audioUri = intent.getData();
        Uri lrcUri = intent.getParcelableExtra("lrcUri");

        if (audioUri == null) {
            Toast.makeText(this, "No audio URI provided.", Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        initializePlayer(audioUri);

        if (lrcUri != null) {
            Log.i(TAG, "LRC Document URI received: " + lrcUri);
            loadLyricFromDocumentUri(lrcUri);
        } else {
            Log.i(TAG, "No LRC Document URI received.");
            lrcIsLoaded = false;
            if (mLrcView != null) {
                mLrcView.reset();
            }
        }
    }

    private void initializePlayer(Uri audioUri) {
        player = new ExoPlayer.Builder(this).build();
        playerView.setPlayer(player);

        MediaItem mediaItem = MediaItem.fromUri(audioUri);
        player.setMediaItem(mediaItem);

        player.setPlayWhenReady(playWhenReady);
        player.seekTo(currentWindow, playbackPosition);

        player.addListener(new Player.Listener() {
            @Override
            public void onPlaybackStateChanged(int playbackState) {
                switch (playbackState) {
                    case Player.STATE_READY:
                        Log.d(TAG, "Player state: READY");
                        // 获取屏幕高度
                        int screenHeight = getResources().getDisplayMetrics().heightPixels;
                        int halfScreenHeight = screenHeight / 2;

                        // 使用 ViewTreeObserver 确保在布局完成后调整高度
                        playerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                            @Override
                            public void onGlobalLayout() {
                                // 移除监听器，避免重复调用
                                playerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                                if (playerView.getHeight() > halfScreenHeight) {
                                    // 设置高度为屏幕高度的一半
                                    playerView.getLayoutParams().height = halfScreenHeight;
                                    playerView.requestLayout();
                                    //todo: 这种情况要占状态栏的区域
                                }
                            }
                        });

                        // If player becomes ready and is set to play, or is already playing
                        if (player.getPlayWhenReady() || player.isPlaying()) {
                            startLyricsUpdater();
                        } else {
                            // Player is ready but paused, update to current position once
                            updateLyricsToCurrentPosition();
                            stopLyricsUpdater(); // Ensure it's stopped if paused
                        }
                        break;
                    case Player.STATE_ENDED:
                        Log.d(TAG, "Player state: ENDED");
                        updateLyricsToCurrentPosition(); // Update to the very end
                        stopLyricsUpdater();
                        // Optionally reset lyrics view or seek to start
                        // if (mLrcView != null) mLrcView.updateTime(0);
                        break;
                    case Player.STATE_BUFFERING:
                        Log.d(TAG, "Player state: BUFFERING");
                        // Lyrics update will naturally pause if isPlaying becomes false
                        // or continue if buffering doesn't stop playback.
                        break;
                    case Player.STATE_IDLE:
                        Log.d(TAG, "Player state: IDLE");
                        stopLyricsUpdater();
                        break;
                }
            }

            @Override
            public void onPositionDiscontinuity(@NonNull Player.PositionInfo oldPosition, @NonNull Player.PositionInfo newPosition, int reason) {
                if (player != null && mLrcView != null) {
                    long currentPosition = newPosition.positionMs;
                    // 调用 LrcView 的 seekTo 方法更新歌词
                    mLrcView.seekTo(currentPosition, false, false);
                }
            }

            @Override
            public void onIsPlayingChanged(boolean isPlaying) {
                Log.d(TAG, "Player isPlaying: " + isPlaying);
                if (isPlaying) {
                    startLyricsUpdater();
                } else {
                    // When pausing, do one final update to the current position
                    updateLyricsToCurrentPosition();
                    stopLyricsUpdater();
                }
            }

            @Override
            public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
                Log.d(TAG, "Player playWhenReady: " + playWhenReady);
                if (playWhenReady && player.getPlaybackState() == Player.STATE_READY) {
                    // If it was paused and now playWhenReady is true, and player is ready
                    startLyricsUpdater();
                } else if (!playWhenReady) {
                    // If playWhenReady becomes false (e.g. user initiated pause)
                    updateLyricsToCurrentPosition();
                    stopLyricsUpdater();
                }
            }

            @Override
            public void onPlayerError(@NonNull PlaybackException error) {
                Log.e(TAG, "Player error: " + error.getMessage(), error);
                Toast.makeText(PlayerActivity.this, "播放出错: " + error.getMessage(), Toast.LENGTH_LONG).show();
                stopLyricsUpdater();
            }
        });

        player.prepare();
        // player.play(); // Playback will start based on playWhenReady state
    }

    // 添加字幕文件
    private void addSubtitleFiles(MediaItem.Builder mediaItemBuilder, Uri uri) {

    }

    private String getMimeTypeForExtension(String ext) {
        switch (ext.toLowerCase()) {
            case "srt":
                return MimeTypes.APPLICATION_SUBRIP;
            case "vtt":
                return MimeTypes.TEXT_VTT;
            default:
                return MimeTypes.APPLICATION_SUBRIP;
        }
    }

    // 更新歌词显示
    private void updateLyrics() {
//        if (player != null && mLrcView != null) {
//            long currentPosition = player.getCurrentPosition();
//            mLrcView.updateTime(currentPosition);
//        }
    }


    private void loadLyricFromDocumentUri(Uri lrcDocUri) {
        ContentResolver resolver = getContentResolver();
        lrcIsLoaded = false; // Reset before loading
        try (InputStream inputStream = resolver.openInputStream(lrcDocUri);
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {

            StringBuilder lrcContent = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                lrcContent.append(line).append("\n");
            }

            if (lrcContent.length() > 0) {
                DefaultLrcParser parser = DefaultLrcParser.getInstance();
                List<LrcRow> lrcRows = parser.getLrcRows(lrcContent.toString());

                if (lrcRows != null && !lrcRows.isEmpty() && mLrcView != null) {
                    mLrcView.setLrcRows(lrcRows);
                    lrcIsLoaded = true;
                    Log.i(TAG, "Lyrics loaded successfully from Document URI.");
                    // After lyrics are loaded, if player is already playing, start updater
                    if (player != null && player.isPlaying()) {
                        startLyricsUpdater();
                    } else if (player != null && player.getPlaybackState() == Player.STATE_READY) {
                        // If player is ready but paused, update to current position once
                        updateLyricsToCurrentPosition();
                    }

                    // 如果你的 LRCView 需要和 Player 同步
                    // mLrcView.setPlayer(player); // or similar method
                    // player.addAnalyticsListener(new EventTimeLogger()); // For timing
                    // player.addAnalyticsListener(new AnalyticsListener() {
                    // @Override
                    // public void onPositionDiscontinuity(@NonNull EventTime eventTime, @NonNull Player.PositionInfo oldPosition, @NonNull Player.PositionInfo newPosition, int reason) {
                    // if (mLrcView != null) {
                    // mLrcView.updateTime(newPosition.positionMs);
                    // }
                    // }
                    // });


                } else {
                    Log.w(TAG, "Failed to parse LRC rows or LrcView is null.");
                    if (mLrcView != null) mLrcView.reset();
                }
            } else {
                Log.w(TAG, "LRC file from Document URI is empty.");
                if (mLrcView != null) mLrcView.reset();
            }

        } catch (IOException e) {
            Log.e(TAG, "Error reading LRC Document URI: " + lrcDocUri, e);
            Toast.makeText(this, "加载歌词文件出错: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            if (mLrcView != null) mLrcView.reset();
        } catch (SecurityException se) {
            Log.e(TAG, "SecurityException reading LRC Document URI: " + lrcDocUri, se);
            Toast.makeText(this, "歌词文件权限错误: " + se.getMessage(), Toast.LENGTH_SHORT).show();
            if (mLrcView != null) mLrcView.reset();
        }
    }

    private void startLyricsUpdater() {
        if (lrcIsLoaded && player != null && player.getPlaybackState() != Player.STATE_IDLE && player.getPlaybackState() != Player.STATE_ENDED) {
            // Remove any existing callbacks to prevent multiple updaters
            lyricsUpdateHandler.removeCallbacks(lyricsUpdateRunnable);
            // Post the first runnable
            lyricsUpdateHandler.post(lyricsUpdateRunnable);
            Log.d(TAG, "Lyrics updater started.");
        }
    }

    private void stopLyricsUpdater() {
        lyricsUpdateHandler.removeCallbacks(lyricsUpdateRunnable);
        Log.d(TAG, "Lyrics updater stopped.");
    }

    private void updateLyricsToCurrentPosition() {
        if (player != null && lrcIsLoaded && mLrcView != null) {
            long currentPosition = player.getCurrentPosition();
            mLrcView.seekTo(currentPosition, false, false);
            Log.d(TAG, "Lyrics updated to position: " + currentPosition);
        }
    }


    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        if (player != null) {
            outState.putLong(KEY_PLAYBACK_POSITION, player.getCurrentPosition());
            outState.putInt(KEY_CURRENT_WINDOW, player.getCurrentMediaItemIndex());
            outState.putBoolean(KEY_PLAY_WHEN_READY, player.getPlayWhenReady());
        } else {
            outState.putLong(KEY_PLAYBACK_POSITION, playbackPosition);
            outState.putInt(KEY_CURRENT_WINDOW, currentWindow);
            outState.putBoolean(KEY_PLAY_WHEN_READY, playWhenReady);
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        // initializePlayer might be called here or in onCreate
        // If player can be null here, ensure checks
        if (player != null && (player.getPlayWhenReady() || player.isPlaying())) {
            startLyricsUpdater();
        }
    }


    @Override
    protected void onResume() {
        super.onResume();
        // If player exists and is meant to be playing, ensure updater is running
        if (player != null) {
            if (player.getPlayWhenReady() || player.isPlaying()) {
                startLyricsUpdater();
            } else {
                // If paused, ensure lyrics reflect current state
                updateLyricsToCurrentPosition();
            }
            // Ensure playerView is connected
            if (playerView.getPlayer() == null) {
                playerView.setPlayer(player);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // When activity is paused, always stop the updater
        stopLyricsUpdater();
        // Update playbackPosition and playWhenReady for saving state if player is not null
        if (player != null) {
            playbackPosition = player.getCurrentPosition();
            playWhenReady = player.getPlayWhenReady();
            // Do not release player here if you want playback to continue in background
            // or be resumable. Release in onDestroy.
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Optionally, if you want to stop updates even more aggressively
        stopLyricsUpdater();
        // playerView.setPlayer(null); // Detach player from view if activity is not visible
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopLyricsUpdater(); // Final cleanup
        releasePlayer();
    }

    private void releasePlayer() {
        if (player != null) {
            // Persist final state before releasing if not done in onPause/onSaveInstanceState
            playbackPosition = player.getCurrentPosition();
            currentWindow = player.getCurrentMediaItemIndex();
            playWhenReady = player.getPlayWhenReady();

            player.release();
            player = null;
            Log.d(TAG, "Player released.");
        }
    }
}